<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>前端js基础 | mozihao</title><meta name="keywords" content="JavaScript基础"><meta name="author" content="mozihao"><meta name="copyright" content="mozihao"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="基本类型boolean、null、undefined、number、string、symbol、bigInt 首先原始类型存储的都是值，是没有函数可以调用的，比如 undefined.toString()     &#x2F;&#x2F;Uncaught TypeError: Cannot read property ‘toString’ of undefined at :1:11  注意：由于Number、Stri">
<meta property="og:type" content="article">
<meta property="og:title" content="前端js基础">
<meta property="og:url" content="https://mo_zi_hao.gitee.io/blog/posts/449/index.html">
<meta property="og:site_name" content="mozihao">
<meta property="og:description" content="基本类型boolean、null、undefined、number、string、symbol、bigInt 首先原始类型存储的都是值，是没有函数可以调用的，比如 undefined.toString()     &#x2F;&#x2F;Uncaught TypeError: Cannot read property ‘toString’ of undefined at :1:11  注意：由于Number、Stri">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/26&gp=0.jpg">
<meta property="article:published_time" content="2021-08-29T15:22:14.600Z">
<meta property="article:modified_time" content="2023-02-04T08:30:09.230Z">
<meta property="article:author" content="mozihao">
<meta property="article:tag" content="JavaScript基础">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/26&gp=0.jpg"><link rel="shortcut icon" href="/blog/img/favicon.png"><link rel="canonical" href="https://mo_zi_hao.gitee.io/blog/posts/449/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/blog/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/blog/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2023-02-04 16:30:09'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    })(window)</script><link rel="stylesheet" type="text/css" href="./css/iconfont.css" media="all"><meta name="generator" content="Hexo 5.4.2"><link rel="alternate" href="/blog/atom.xml" title="mozihao" type="application/atom+xml">
</head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/%E6%B5%B7%E8%B4%BC008.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">24</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">16</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">11</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fas fa-heart"></i><span> 前端知识思维导图</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gitee.com/mo_zi_hao/picsBed/raw/master/image/26&amp;gp=0.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/blog/">mozihao</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fas fa-heart"></i><span> 前端知识思维导图</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">前端js基础</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-08-29T15:22:14.600Z" title="发表于 2021-08-29 23:22:14">2021-08-29</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-02-04T08:30:09.230Z" title="更新于 2023-02-04 16:30:09">2023-02-04</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/JavaScript/">JavaScript</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">9.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>35分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="前端js基础"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h3 id="基本类型"><a href="#基本类型" class="headerlink" title="基本类型"></a>基本类型</h3><p>boolean、null、undefined、number、string、symbol、bigInt</p>
<p>首先原始类型存储的都是值，是没有函数可以调用的，比如 undefined.toString()    </p>
<p>//Uncaught TypeError: Cannot read property ‘toString’ of undefined at <anonymous>:1:11</p>
<ul>
<li><p>注意：由于Number、String，Boolean为包装类型，会把基本类型转换为对象类型，所以以上的三种基本类型直接调用toString是不会报错的，并能正常调用</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;aaa&#x27;</span>.toString()   <span class="comment">// &#x27;aaa&#x27;</span></span><br><span class="line"><span class="literal">true</span>.toString()   <span class="comment">// &#x27;true&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="number">1.</span>toString()  <span class="comment">// Uncaught SyntaxError: Invalid or unexpected token</span></span><br></pre></td></tr></table></figure>

<p>⚠️但是<strong>1.toString()<strong>为什么会报错呢，</strong>数字直接量</strong></p>
<p>原因是JavaScript 规范中规定的数字直接量可以支持四种写法：十进制数、二进制整数、八进制整数和十六进制整数。</p>
<p>十进制的 Number 可以带小数，<strong>小数点前后部分都可以省略</strong>，但是不能同时省略，所以**1.toString()**被当成是一个带有小数点的数字整体了</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">.1</span>   <span class="comment">// 0.1</span></span><br><span class="line"><span class="number">1.</span>   <span class="comment">// 1</span></span><br><span class="line"><span class="number">1.1</span>  <span class="comment">// 1.1</span></span><br></pre></td></tr></table></figure>

<p>用<strong>数字直接量想调用toString</strong>方法等，需要将点单独成为一个 token(语义单元)，就要加入空格</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> .toString() 	<span class="comment">// &#x27;1&#x27;    加一个空格</span></span><br><span class="line"><span class="comment">//或者 </span></span><br><span class="line">(<span class="number">1</span>).toString()  <span class="comment">// &#x27;1&#x27;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<p>参数是对象</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params">person</span>) </span>&#123;</span><br><span class="line">  person.age = <span class="number">26</span></span><br><span class="line">  person = &#123;</span><br><span class="line">    name: <span class="string">&quot;yyy&quot;</span>,</span><br><span class="line">    age: <span class="number">30</span></span><br><span class="line">  &#125;</span><br><span class="line"> </span><br><span class="line">  <span class="keyword">return</span> person</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> p1 = &#123;</span><br><span class="line">  name: <span class="string">&quot;xxx&quot;</span>,</span><br><span class="line">  age: <span class="number">25</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> p2 = test(p1)</span><br><span class="line"><span class="built_in">console</span>.log(p1) <span class="comment">// -&gt;&#123;name: &quot;xxx&quot;, age: 26&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(p2) <span class="comment">// -&gt; &#123;name: &quot;yyy&quot;, age: 30&#125;</span></span><br></pre></td></tr></table></figure>

<p>解：<br>函数传递的是对象指针的副本<br>当到函数内部修改参数属性，p1被修改<br>当在重新为person分配了一个对象此时放回的person的地址是一个新的地址不影响p1</p>
<h3 id="类型判断–typeof"><a href="#类型判断–typeof" class="headerlink" title="类型判断–typeof"></a>类型判断–typeof</h3><p><strong>原始类型的判断使用typeof，除了null之外都可判断正确的类型（null判断出来是Object，）</strong></p>
<p>typeof null 会输出 object   —— 在 JS 的最初版本中使用的是 32 位系统，为了性能考虑使用低位存储变量的类型信息，000 开头代表是对象，然而 null 表示为全零，所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了，但是对于这个 Bug 却是一直流传下来</p>
<p>但typeof对于对象来说，除了函数都会显示object，所以说typeof并不能准确判断变量到底是什么类型</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typeof</span> [] <span class="comment">// ’object’</span></span><br><span class="line"><span class="keyword">typeof</span> &#123;&#125; <span class="comment">// ’object’</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">console</span>.log  <span class="comment">// ’function’</span></span><br></pre></td></tr></table></figure>

<h3 id="对象判断—instanceof"><a href="#对象判断—instanceof" class="headerlink" title="对象判断—instanceof"></a>对象判断—instanceof</h3><p>判断对象还是考虑使用instanceof，但使用instanceof是无法判断直接原始类型的，所以instanceof也不能百分百可信；例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">“hellow world” <span class="keyword">instanceof</span> <span class="built_in">String</span>    <span class="comment">//false</span></span><br><span class="line">h</span><br><span class="line">而需要 <span class="keyword">new</span> <span class="built_in">String</span>(<span class="string">&quot;hellow world&quot;</span>) <span class="keyword">instanceof</span> <span class="built_in">String</span>  <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>可以使用Symbol.hasInstance自定义instanceof的行为</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PrimitiveString</span> </span>&#123;</span><br><span class="line">  <span class="keyword">static</span> [<span class="built_in">Symbol</span>.hasInstance](x) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">typeof</span> x === <span class="string">&#x27;string&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;hello world&#x27;</span> <span class="keyword">instanceof</span> PrimitiveString) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h4 id="instanceof实现原理"><a href="#instanceof实现原理" class="headerlink" title="instanceof实现原理"></a>instanceof实现原理</h4><p><strong>instanceof内部机制是通过判断对象的原型链中是不是能找到类型的prototype</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">myInstanceof</span>(<span class="params">left,right</span>)</span>&#123;   <span class="comment">//left： 对象    right： 类型</span></span><br><span class="line">    <span class="keyword">let</span> prototype = right.prototype</span><br><span class="line">    left = left._proto_</span><br><span class="line">    <span class="keyword">while</span>(<span class="literal">true</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span>(left === <span class="literal">null</span> || left === <span class="literal">undefined</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(prototype === left)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">        left = left._proto_</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>循环判断对象的原型是否等于类型的原型，知道对象原型为null，因为<strong>原型链最终为null</strong></p>
<h3 id="类型转换"><a href="#类型转换" class="headerlink" title="类型转换"></a>类型转换</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">number =&gt; boolean   除了<span class="number">0</span>、-<span class="number">0</span>、<span class="literal">NaN</span>都为<span class="literal">true</span></span><br><span class="line">string =&gt; boolean 除了空字符串都为<span class="literal">true</span></span><br><span class="line"><span class="literal">undefined</span>、<span class="literal">null</span> =&gt; boolean   <span class="literal">false</span></span><br><span class="line"><span class="literal">null</span> =&gt; number  <span class="number">0</span></span><br><span class="line"><span class="literal">undefined</span> =&gt; number <span class="literal">NaN</span></span><br><span class="line">引用类型(array,object即使是为空) =&gt;boolean   <span class="literal">true</span></span><br><span class="line">number =&gt; string  例：<span class="number">5</span>=&gt;<span class="string">&#x27;5&#x27;</span></span><br><span class="line">boolean、函数、<span class="built_in">Symbol</span> =&gt; string   例：<span class="literal">true</span> =&gt; <span class="string">&quot;true&quot;</span></span><br><span class="line">array =&gt; string  例：[<span class="number">1</span>,<span class="number">2</span>] =&gt; <span class="string">&quot;1,2&quot;</span></span><br><span class="line"><span class="built_in">Object</span> =&gt; string  例：&#123;&#125;  =&gt; <span class="string">&quot;[object,object]&quot;</span></span><br><span class="line">string =&gt; number   例子：“<span class="number">1</span>”=&gt; <span class="number">1</span>       <span class="string">&quot;a&quot;</span>=&gt; <span class="literal">NaN</span></span><br><span class="line">array =&gt; number  空数组为<span class="number">0</span>，存在一个元素且为数字转成数字，其他情况<span class="literal">NaN</span></span><br><span class="line">除了数组的引用类型 =&gt;number   <span class="literal">NaN</span></span><br><span class="line">symbol =&gt; number  抛出错误</span><br></pre></td></tr></table></figure>

<h3 id="转Boolean"><a href="#转Boolean" class="headerlink" title="转Boolean"></a>转Boolean</h3><p>在条件判断时，除了 undefined， null， false， NaN， ‘’ (空字符串)， 0， -0，其他所有值都转为 true，包括所有对象。</p>
<h3 id="对象转基本类型"><a href="#对象转基本类型" class="headerlink" title="对象转基本类型"></a>对象转基本类型</h3><p>对象在转基本类型的时候会调用内置的[[ToPrimitive]]，该函数的内部执行：如果不是基本类型则会调用 x.valueOf()方法，x.toString()；返回转换的值</p>
<p>对象类型转换，在对象进行类型转换的时候我们可以重写valueOf，toString方法。</p>
<h4 id="面试题："><a href="#面试题：" class="headerlink" title="面试题："></a>面试题：</h4><p>​    <strong>var a = {num: 0},使if(a == 1&amp;&amp; a==2&amp;&amp;a==3){console.log(‘ok’)},打印出ok</strong></p>
<p>解：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;<span class="attr">num</span>:<span class="number">0</span>&#125;</span><br><span class="line">a.valueOf = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="keyword">return</span> ++a.num &#125;</span><br><span class="line"><span class="keyword">if</span>(a ==<span class="number">1</span>&amp;&amp;a==<span class="number">2</span>&amp;&amp;a==<span class="number">3</span>)&#123; <span class="built_in">console</span>.log(‘ok’) &#125;</span><br></pre></td></tr></table></figure>

<p>也可以重写Symbol.toPrimitive，该方法在转原始类型时调用优先级最高</p>
<p>(优先级：Symbol.toPrimitive  &gt;  valueOf  &gt;  toString )</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">  num: <span class="number">0</span>,</span><br><span class="line">  <span class="function"><span class="title">valueOf</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="title">toString</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;1&#x27;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  [<span class="built_in">Symbol</span>.toPrimitive]() &#123;</span><br><span class="line">    <span class="keyword">return</span> ++<span class="built_in">this</span>.num</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(a==<span class="number">1</span>&amp;&amp;a==<span class="number">2</span>&amp;&amp;a==<span class="number">3</span>)&#123; <span class="built_in">console</span>.log(<span class="string">&#x27;ok&#x27;</span>) &#125;</span><br></pre></td></tr></table></figure>

<h3 id="四则运算符"><a href="#四则运算符" class="headerlink" title="四则运算符"></a>四则运算符</h3><h4 id="加法运算符"><a href="#加法运算符" class="headerlink" title="加法运算符"></a>加法运算符</h4><p>加法运算符不同于其他几个运算符，加法运算符特点如下：</p>
<ol>
<li><p>运算中其中一方为字符串，另一方也转为字符串  例：1+ ‘1’ // 11    ;   true + true  // 2</p>
</li>
<li><p>如果一方不是字符串或者数字，那么会将他转换为数字或者字符串     例：2 + [1,2,3]  // “21,2,3’   此处数组通过toString转为字符串 ‘1,2,3’</p>
</li>
</ol>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意： <span class="string">&#x27;a&#x27;</span> + + <span class="string">&#x27;b&#x27;</span>  <span class="comment">// ’aNaN’  因为 +’b’ 结果为NaN</span></span><br></pre></td></tr></table></figure>

<p>除了加法的其他运算符，只要其中一方为数字，那么另一方就会转为数字</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">4</span> * <span class="string">&#x27;3&#x27;</span>  <span class="comment">// 12</span></span><br><span class="line"><span class="number">4</span> * []  <span class="comment">// 0 空数组转数字为0</span></span><br><span class="line"><span class="number">4</span> * [<span class="number">1</span>,<span class="number">2</span>]  <span class="comment">//NaN  非空数组转数字为NaN</span></span><br></pre></td></tr></table></figure>

<h4 id="比较运算符"><a href="#比较运算符" class="headerlink" title="比较运算符"></a>比较运算符</h4><ol>
<li><p>如果是对象，就通过toPrimitive 转换对象</p>
</li>
<li><p>如果是字符串，就通过unicode字符索引来比较</p>
</li>
</ol>
<p>例如：</p>
<p>对象：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123;</span><br><span class="line"><span class="function"><span class="title">valueOf</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">&#125;,</span><br><span class="line"><span class="function"><span class="title">toString</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="string">&#x27;1&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">a &gt; -<span class="number">1</span>  <span class="comment">// true  跟上面的面试题类似 转换的时候调用valueOf转换为原始类型</span></span><br></pre></td></tr></table></figure>

<p>求与字符串相加之和，使用Number(xx)，进行类型转换再进行相加</p>
<h4 id="面试题"><a href="#面试题" class="headerlink" title="面试题"></a>面试题</h4><p>0.1 + 0.2 != 0.3</p>
<p>因为计算机对数据的存储是使用二进制的，很多小数在二进制中是无限循环的一些数字，js使用了浮点数标准（IEE754）会裁剪其中的数字，会将64位的二进制数分为三段：第一位表示符号，11位用来表示指数，其他位表示有效位</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0.20000000000000000000000000002</span> === <span class="number">0.2</span> <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0.1</span>+<span class="number">0.2</span>   <span class="comment">//0.30000000000000004</span></span><br></pre></td></tr></table></figure>

<p>使用toFixed()方法，规定小数的位数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseFloat</span>((<span class="number">0.1</span>+<span class="number">0.2</span>).toFixed(<span class="number">10</span>)) === <span class="number">0.3</span></span><br></pre></td></tr></table></figure>



<h3 id="等号"><a href="#等号" class="headerlink" title="等号 =="></a>等号 ==</h3><p>等号 == 存在着隐式转换，比较前</p>
<ol>
<li>先判断两边的类型是否相同，相同的话就比较大小</li>
<li>不相同的话就判断两边是否为null和undefined比较，是则返回true，不是则进行类型转换</li>
<li>判断是否为string类型和number类型，是的话将string转number</li>
<li>判断其中一方是否为boolean类型，是的话就会把boolean转为number类型</li>
<li>判断其中一方是否为object类型，且另一方为string、number、symbol类型，是的话就将object类型转成原始类型再进行判断</li>
</ol>
<h4 id="注意："><a href="#注意：" class="headerlink" title="注意："></a>注意：</h4><ol>
<li><p>如果两者都为引用类型（array，object），则比较的是两边的地址</p>
<p>例如</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[]==[] <span class="comment">//false </span></span><br><span class="line">&#123;&#125;==&#123;&#125; <span class="comment">//false</span></span><br></pre></td></tr></table></figure></li>
<li><p>如果两者的类型不一样则转换为number类型，如果存在一边是boolean类型，则boolean类型转换成number类型，再进行比较</p>
</li>
</ol>
<p>我们一起来看看下面的这两个隐式转换</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[] ==![] 和 &#123;&#125; ==!&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>上面讲过[]==[]和{}=={}两者都为false，那么[]==![]和{}==!{}又是什么呢，这里应该看到这么问，大家都觉得是有坑是吧哈哈哈，[]==![]为true；{}==!{}为false；为什么呢</p>
<h4 id="解：-true"><a href="#解：-true" class="headerlink" title="解：[] == ![]     //true"></a>解：[] == ![]     //true</h4><p>[]==![]  因为逻辑运算符 ! 的优先级是大于==的，所以我们先看右边，![]因为[]转布尔类型是true，因为引用类型（array，object）转boolean都为true，所以![]为false，==的运算顺序是从左到右，因为两边比较的类型不相同，所以[]转number类型为0，false转number类型也为0，所以两边都为0，所以为true</p>
<p>先右边：![]  -&gt;  !true  -&gt;  false  -&gt;  0</p>
<p>再到左边： []  -&gt;(引用类型转number) 0</p>
<h4 id="解：-false"><a href="#解：-false" class="headerlink" title="解：{} == !{}    //false"></a>解：{} == !{}    //false</h4><p>{}==!{}同理，{}先转成原始类型[object object],然后转boolean类型为true，然后!{}为false，false转number类型为0，而{}转number类型为NaN，所以NaN == 0 为false，（因为无论是使用==还是===和任何类型比较的结果都为false包括和它本身比较，那么怎么判断NaN呢，这里需要用到Number的自带方法— Number.isNaN(xxx)返回的是一个布尔值）</p>
<p>先右边： !{}  -&gt;  !true  -&gt;  false  -&gt; 0</p>
<p>再左边： {}  -&gt; (引用类型转number) NaN</p>
<p>发现最后都是往boolean和number类型的转换，最后比较两边是否相等</p>
<h3 id="全等"><a href="#全等" class="headerlink" title="全等 ==="></a>全等 ===</h3><h4 id="全等：不存在隐式转换"><a href="#全等：不存在隐式转换" class="headerlink" title="全等：不存在隐式转换"></a>全等：不存在隐式转换</h4><p>但是</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">NaN</span> === <span class="literal">NaN</span> <span class="comment">// false</span></span><br><span class="line">+<span class="number">0</span> === -<span class="number">0</span> <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>这里NaN理论上应该是相等的才对啊是吧，而正零和负零应该是不相等才对啊，那么如果我们需要正确判断他们，但是全等又不准确，那怎么办呢</p>
<h4 id="Object-is"><a href="#Object-is" class="headerlink" title="Object.is()"></a>Object.is()</h4><p>这个方法跟全等差不多，判断两个值是否为同一个值，是可以区分正负零和判断出NaN</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.is(-<span class="number">0</span>,+<span class="number">0</span>)  <span class="comment">//false</span></span><br><span class="line"><span class="built_in">Object</span>.is(<span class="literal">NaN</span>,<span class="literal">NaN</span>) <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>但是这个方法存在兼容问题：<strong>IE是不兼容的</strong>，如果用在小程序还好，用在pc或者h5端的话慎重！</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/1614096184167.png" alt="Object.is兼容性"></p>
<p>当然判断NaN的方法也可以使用Number.isNaN()，返回的是一个布尔值</p>
<h3 id="原型"><a href="#原型" class="headerlink" title="原型"></a>原型</h3><p>每个实例对象里都有一个下划线原型_proto_，该原型指向prototype，该原型是用来共享实例和方法的，prototype里面有一个构造函数constructor里面是用来存放共享的方法</p>
<ol>
<li>所有的对象的最终的指向是Object</li>
<li>所有函数的最终指向是Function</li>
<li>函数的prototype是一个对象</li>
<li>对象的_proto_属性指向原型，_proto_将对象和原型连接起来组成的原型链</li>
</ol>
<h3 id="原型链"><a href="#原型链" class="headerlink" title="原型链"></a>原型链</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">person</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">    <span class="built_in">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">person.prototype.run = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> a = <span class="keyword">new</span> person(<span class="string">&#x27;xiaoming&#x27;</span>,<span class="number">12</span>)</span><br><span class="line"><span class="built_in">console</span>.dir(a)</span><br></pre></td></tr></table></figure>

<p>结果如下截图:</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/55555clipboard.png" alt="原型链"></p>
<p>这样看着好像还是有点混乱,那么请看下图</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/clipboard-1614145265099.png"></p>
<h3 id="原型继承和class继承"><a href="#原型继承和class继承" class="headerlink" title="原型继承和class继承"></a>原型继承和class继承</h3><h4 id="原型继承："><a href="#原型继承：" class="headerlink" title="原型继承："></a>原型继承：</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">    <span class="built_in">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">Parent.prototype.run = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line">Child.prototype = <span class="keyword">new</span> Parent()</span><br><span class="line"><span class="keyword">const</span> child = <span class="keyword">new</span> Child()</span><br><span class="line"><span class="built_in">console</span>.log(child)</span><br></pre></td></tr></table></figure>

<p>child的结构如下图：</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/child.png" alt="child的结构"></p>
<p><strong>注意：此方法只继承到了Parent的方法(run)，没有继承到Parent的属性(name,age)</strong></p>
<h4 id="借用构造函数实现继承："><a href="#借用构造函数实现继承：" class="headerlink" title="借用构造函数实现继承："></a>借用构造函数实现继承：</h4><p>（call，apply，bind方法实现继承（通过改变this的指向实现继承），这三个方法的用法就不在这细讲，原理都一样，这里用call来作例子）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line"><span class="built_in">this</span>.name = name</span><br><span class="line"><span class="built_in">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">Parent.prototype.run = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">Parent.call(<span class="built_in">this</span>,name,age)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> child = <span class="keyword">new</span> Child(<span class="string">&quot;xiaoming&quot;</span>,<span class="string">&quot;12&quot;</span>)</span><br><span class="line"><span class="built_in">console</span>.log(child)</span><br></pre></td></tr></table></figure>

<p>child的结构如下图:</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/child2.png"></p>
<p><strong>注意：此方法只继承了Parent的属性，但不能继承到Parent的方法</strong></p>
<h4 id="组合继承："><a href="#组合继承：" class="headerlink" title="组合继承："></a>组合继承：</h4><p>（没错就是上面两个继承方式的组合）:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">    <span class="built_in">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">Parent.prototype.run = <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    Parent.call(<span class="built_in">this</span>,name,age)  <span class="comment">//继承属性</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Child.prototype = <span class="keyword">new</span> Parent() <span class="comment">//调用构造函数的时候会为实例添加一个指向最初原型prototype指针----继承Parent原型（prototype）中共享的方法</span></span><br><span class="line">Child.prototype.constructor = Child    <span class="comment">//这里不改变原型的构造器，则会指向Parent的构造器</span></span><br><span class="line"><span class="keyword">const</span> child = <span class="keyword">new</span> Child(<span class="string">&quot;xiaoming&quot;</span>,<span class="string">&quot;12&quot;</span>)</span><br><span class="line">child.run() <span class="comment">//xiaoming</span></span><br><span class="line">child <span class="keyword">instanceof</span> Parent <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<h4 id="寄生组合继承："><a href="#寄生组合继承：" class="headerlink" title="寄生组合继承："></a>寄生组合继承：</h4><p>—继承的方案中比较完美的，在组合继承中省去了继承父类的无用属性的内存占用</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Parent</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name</span><br><span class="line">    <span class="built_in">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">Parent.prototype.run = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Child</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    Parent.call(<span class="built_in">this</span>,name,age)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Child.prototype = <span class="built_in">Object</span>.create(Parent.prototype,&#123;   </span><br><span class="line">    <span class="title">constructor</span>:&#123;         <span class="comment">//重写构造函数</span></span><br><span class="line">        value: Child,</span><br><span class="line">        enumerable:<span class="literal">false</span>,     <span class="comment">//是否可枚举</span></span><br><span class="line">        writable: <span class="literal">true</span>,       <span class="comment">//是否可修改</span></span><br><span class="line">        configurable: <span class="literal">true</span>    <span class="comment">//是否可配置</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> child = <span class="keyword">new</span> Child(<span class="string">&#x27;xiaoming&#x27;</span>,<span class="string">&#x27;12&#x27;</span>)</span><br><span class="line">child.run()  <span class="comment">//xiaoming</span></span><br><span class="line">child <span class="keyword">instanceof</span> Parent <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(child)</span><br></pre></td></tr></table></figure>

<p>child的结构如下图：</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/child3.png"></p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/child4.png"></p>
<h4 id="class继承"><a href="#class继承" class="headerlink" title="class继承"></a>class继承</h4><p>class是语法糖，本质还是函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">person</span></span>&#123;&#125;</span><br><span class="line">person <span class="keyword">instanceof</span> <span class="built_in">Function</span>  <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>ES6的新增语法，使用class实现继承</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name</span><br><span class="line">        <span class="built_in">this</span>.age = age</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="title">run</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>.name)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span> <span class="keyword">extends</span> <span class="title">Parent</span></span>&#123;     <span class="comment">//extends继承于Parent，</span></span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">        <span class="built_in">super</span>(name,age)     <span class="comment">//这里的super相当于Parent.call(this,name,age)</span></span><br><span class="line">        <span class="built_in">this</span>.name = name</span><br><span class="line">        <span class="built_in">this</span>.age = age</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> child = <span class="keyword">new</span> Child(<span class="string">&quot;xiaoming&quot;</span>,<span class="string">&quot;12&quot;</span>)</span><br><span class="line">child.run() <span class="comment">//xiaoming</span></span><br><span class="line">child <span class="keyword">instanceof</span> Parent  <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>child的结构如下图:</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/child5.png"></p>
<h3 id="this"><a href="#this" class="headerlink" title="this"></a>this</h3><ol>
<li>非严格模式下，function的this指向window</li>
<li>一个对象中谁调用this，this就指向谁</li>
<li>new 一个对象，this就绑定到这个对象</li>
<li>箭头函数是没有this的，在箭头函数中调用this是会在上一层作用域去查找，没有则再向上查找，直到查找到最外层的window的作用域，指向window为止</li>
</ol>
<h4 id="注意：-1"><a href="#注意：-1" class="headerlink" title="注意："></a>注意：</h4><p><strong>箭头函数是无法通过bind，call，apply改变this的指向的</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> fn2 = <span class="function"><span class="keyword">function</span> <span class="title">fn1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> fn.apply()</span><br><span class="line">  &#125;.apply(a)</span><br><span class="line">&#125;</span><br><span class="line">fn2()</span><br></pre></td></tr></table></figure>

<p><strong>可以从上述代码中发现，不管我们给函数 apply几次，fn 中的 this 永远由第一次 apply决定，所以结果永远是 window</strong></p>
<p>一般情况下我们可以使用bind，apply，call方法改变this的指向例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123; <span class="attr">name</span>: ‘小明’&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">Console.log(<span class="built_in">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line">foo.bind(a)()   <span class="comment">// 小明</span></span><br></pre></td></tr></table></figure>

<p>但可能有时候会出现多个不同情况，需要根据优先级的最高来决定this的最终指向</p>
<p><strong>this的最终指向优先级大–&gt;小 ： new -&gt; bind,call,apply-&gt;静态量调用obj.foo()的调用形式-&gt;foo的调用形式</strong></p>
<p><strong>注意：箭头函数的this一但被绑定，就不会再被任何方式改变</strong></p>
<h4 id="手写call"><a href="#手写call" class="headerlink" title="手写call"></a>手写call</h4><p>用法： 对象.call(对象, …)</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.myCall = <span class="function"><span class="keyword">function</span>(<span class="params">context</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="keyword">typeof</span> <span class="built_in">this</span> !== <span class="string">&#x27;function&#x27;</span>)&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    context = context || <span class="built_in">window</span></span><br><span class="line">    context.fn = <span class="built_in">this</span></span><br><span class="line">    <span class="keyword">const</span> args = [...arguments].slice(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">const</span> result = context.fn(...args)</span><br><span class="line">    <span class="keyword">delete</span> context.fn</span><br><span class="line">   <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="手写apply"><a href="#手写apply" class="headerlink" title="手写apply"></a>手写apply</h4><p>用法： 对象.apply(对象,[….])</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.myApply = <span class="function"><span class="keyword">function</span>(<span class="params">context</span>)</span>&#123;</span><br><span class="line">   <span class="keyword">if</span>(<span class="keyword">typeof</span> <span class="built_in">this</span> !== <span class="string">&#x27;function&#x27;</span>)&#123;</span><br><span class="line">       <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>)</span><br><span class="line">   &#125;</span><br><span class="line">   context = context || <span class="built_in">window</span></span><br><span class="line">   context.fn = <span class="built_in">this</span></span><br><span class="line">   <span class="keyword">let</span> result</span><br><span class="line">   <span class="keyword">if</span>(<span class="built_in">arguments</span>[<span class="number">1</span>])&#123;</span><br><span class="line">       result = context.fn(...arguments[<span class="number">1</span>])</span><br><span class="line">   &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">       result = context.fn()</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">delete</span> context.fn</span><br><span class="line">   <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="手写bind"><a href="#手写bind" class="headerlink" title="手写bind"></a>手写bind</h4><p>用法： 对象.bind(对象, …)</p>
<p>(bind和call、apply不同的是bind是需要返回一个函数)</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.myBind = <span class="function"><span class="keyword">function</span>(<span class="params">context</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="keyword">typeof</span> <span class="built_in">this</span> !== <span class="string">&#x27;function&#x27;</span>)&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">const</span> _this = <span class="built_in">this</span></span><br><span class="line">    <span class="keyword">let</span> args = [...arguments].slice(<span class="number">1</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="title">F</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(<span class="built_in">this</span> <span class="keyword">instanceof</span> F)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> _this(...args, ...arguments)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> _this.apply(context, args.concat(...arguments))</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="手写call-apply-bind总结："><a href="#手写call-apply-bind总结：" class="headerlink" title="手写call,apply,bind总结："></a>手写call,apply,bind总结：</h4><p>call实现原理：保存当前方法的this,然后将参数传入这个this</p>
<p>apply实现原理： 和call差不多，传入参数不一样</p>
<p>bind实现原理：需要返回一个函数</p>
<h3 id="new的实现"><a href="#new的实现" class="headerlink" title="new的实现"></a>new的实现</h3><ol>
<li><p>新建一个对象</p>
</li>
<li><p>链接到原型链</p>
</li>
<li><p>绑定this</p>
</li>
<li><p>返回新对象</p>
</li>
</ol>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">create</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;</span><br><span class="line">    <span class="keyword">let</span> Con = [].shift.call(<span class="built_in">arguments</span>)  <span class="comment">//这里的意思是将arguments类数组转数组然后拿到第一个参数</span></span><br><span class="line">    obj._proto_ = Con.prototype</span><br><span class="line">    <span class="keyword">let</span> result = Con.apply(obj,<span class="built_in">arguments</span>)</span><br><span class="line">    <span class="keyword">return</span> result <span class="keyword">instanceof</span> <span class="built_in">Object</span> ? result : obj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h3><p>闭包就是函数A内部有一个函数B，函数B可以访问到函数A中的变量，那么函数B就是闭包</p>
<p>例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="keyword">var</span> a = <span class="number">1</span></span><br><span class="line"><span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">	Conso.log(a)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面输出的结果都是6，因为定时器是宏任务，是异步的所以当执行定时器的时候，此时的i已经是6了</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">1</span>;i&lt;=<span class="number">5</span>;i++)&#123;</span><br><span class="line">	<span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> <span class="title">timer</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="built_in">console</span>.log(i)</span><br><span class="line">	&#125;,i*<span class="number">1000</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>所以我们可以使用闭包的方式，来解决这个问题，输出我们想要的结果（输出1到5）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">1</span>;i&lt;=<span class="number">5</span>;i++)&#123;</span><br><span class="line">	(<span class="function"><span class="title">fucntion</span>(<span class="params">j</span>)</span>&#123;</span><br><span class="line">		<span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">			<span class="built_in">console</span>.log(j);</span><br><span class="line">		&#125;,j*<span class="number">1000</span>)</span><br><span class="line">	&#125;)(i)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当然了解决这个问题的方法其实也不止这个，还可以使用<strong>setTimeout的第三个参数</strong>,这个参数会当中timer函数的参数传入</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">1</span>;i &lt;=<span class="number">5</span>;i++)&#123;</span><br><span class="line">	<span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> <span class="title">timer</span>(<span class="params">j</span>)</span>&#123;</span><br><span class="line">		<span class="built_in">console</span>.log(j)</span><br><span class="line">	&#125;,i*<span class="number">1000</span>,i)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>还有一种方法是使用块级作用域let变量声明</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i =<span class="number">1</span>;i&lt;=<span class="number">5</span>;i++)&#123;</span><br><span class="line">	<span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="built_in">console</span>.log(i)</span><br><span class="line">	&#125;,i*<span class="number">1000</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="闭包的运用场景："><a href="#闭包的运用场景：" class="headerlink" title="闭包的运用场景："></a>闭包的运用场景：</h4><ol>
<li>setTimeout</li>
<li>防抖和节流</li>
<li>单例模式</li>
</ol>
<h5 id="防抖："><a href="#防抖：" class="headerlink" title="防抖："></a>防抖：</h5><p>在高频触发的事件中，触发n次只执行一次，每次的触发都会把上一次的事件清除，再重新计算时间</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">fn,interval</span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> timer;</span><br><span class="line"><span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    	<span class="keyword">let</span> context = <span class="built_in">this</span>;</span><br><span class="line">       <span class="keyword">let</span> arg = <span class="built_in">arguments</span>;</span><br><span class="line">		<span class="built_in">clearTimeout</span>(timer);</span><br><span class="line">        timer = <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 将外部传入的函数的执行放在setTimeout中</span></span><br><span class="line">            fn.call(context, ...args);</span><br><span class="line">        &#125;, interval);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>防抖运用场景：</p>
<ol>
<li><p>search搜索联想，用户在不断输入值时，用防抖来节约请求资源。</p>
</li>
<li><p>频繁操作点赞和取消点赞，因此需要获取最后一次操作结果并发送给服务器</p>
</li>
</ol>
<h5 id="节流："><a href="#节流：" class="headerlink" title="节流："></a>节流：</h5><p>也是用于高频触发的事件，触发n次只执行一次，但他和防抖的区别是节流是在于节流是每隔一段事件内触发一次，就是在点击的第一次开始计算，然后在这段时间内的所触发的事件都会被return掉，好比漏水的水龙头，在一个滴水的状态里，即使里面有再多的水流出，但还是一段时间内只滴下一滴水</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> (<span class="params">fn,interval</span>)</span>&#123;</span><br><span class="line">        <span class="keyword">var</span> timer</span><br><span class="line">        <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">let</span> context = <span class="built_in">this</span></span><br><span class="line">            <span class="keyword">let</span> args = <span class="built_in">arguments</span></span><br><span class="line">            <span class="keyword">if</span>(!timer)&#123;</span><br><span class="line">               <span class="keyword">return</span></span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                timer = <span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">                    fn.call(context,...args)</span><br><span class="line">                &#125;,interval)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>节流的运用场景：</p>
<ol>
<li>鼠标不断点击触发，mousedown(单位时间内只触发一次)</li>
<li>window触发resize的时候，不断的调整浏览器窗口大小会不断的触发这个事件，用防抖来让其只触发一次</li>
</ol>
<h5 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h5><p>使用闭包的形式，保存创建的div，使div只创建一次</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> createLoginLayer = (<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> div;</span><br><span class="line">    <span class="comment">//使用闭包实现单例</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span> ( !div )&#123;</span><br><span class="line">            div = <span class="built_in">document</span>.createElement( <span class="string">&#x27;div&#x27;</span> );</span><br><span class="line">            div.innerHTML = <span class="string">&#x27;我是登录浮窗&#x27;</span>;</span><br><span class="line">            div.style.display = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">            <span class="built_in">document</span>.body.appendChild( div );</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> div;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;)();</span><br><span class="line"></span><br><span class="line"><span class="comment">//点击的时候我们才开始创建div这个弹窗</span></span><br><span class="line"><span class="built_in">document</span>.getElementById( <span class="string">&#x27;loginBtn&#x27;</span> ).onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> loginLayer = createLoginLayer();</span><br><span class="line">    loginLayer.style.display = <span class="string">&#x27;block&#x27;</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h3 id="浅拷贝"><a href="#浅拷贝" class="headerlink" title="浅拷贝"></a>浅拷贝</h3><p>问题：有些时候，我们需要操作对象类型的数据，但并不希望它影响到原数据，这时我们就可以使用浅拷贝来解决这个问题，因为引用类型的赋值就是复制了地址，修改了其中一个，另一个也会跟着修改</p>
<p>例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">age: <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> b = a</span><br><span class="line">b.age = <span class="number">2</span>  </span><br><span class="line"><span class="built_in">console</span>.log(a.age)   <span class="comment">//2</span></span><br></pre></td></tr></table></figure>



<p>浅拷贝原理：浅拷贝只是创建了一个新的对象，复制了原有对象的基本类型的值；但在引用类型的深层嵌套的情况下还是会出现新对象的修改会改变原对象</p>
<h4 id="实现浅拷贝："><a href="#实现浅拷贝：" class="headerlink" title="实现浅拷贝："></a>实现浅拷贝：</h4><h5 id="ES6的assign"><a href="#ES6的assign" class="headerlink" title="ES6的assign"></a>ES6的assign</h5><p>可以使用ES6的assign，assign会将所有属性的值拷贝到新的对象中，如果拷贝的属性值是对象的话，拷贝的是地址</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">age: <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> b = <span class="built_in">Object</span>.assgin(&#123;&#125;,a)</span><br><span class="line">b.age = <span class="number">2</span></span><br><span class="line"><span class="built_in">console</span>.log(a.age)  <span class="comment">//1</span></span><br></pre></td></tr></table></figure>

<h5 id="还可以使用…运算符实现浅拷贝"><a href="#还可以使用…运算符实现浅拷贝" class="headerlink" title="还可以使用…运算符实现浅拷贝"></a>还可以使用…运算符实现浅拷贝</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a =&#123;</span><br><span class="line">age:<span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> b = &#123;...a&#125;</span><br><span class="line">b.age = <span class="number">2</span></span><br><span class="line"><span class="built_in">console</span>.log(a.age)   <span class="comment">//1</span></span><br></pre></td></tr></table></figure>

<p><strong>注意：浅拷贝只解决了第一层的问题，如果接下去的值中还有对象的话，那么就又回到最开始的话题了，两者享有相同的地址。要解决这个问题，我们就得使用深拷贝了。</strong></p>
<h5 id="数组的浅拷贝"><a href="#数组的浅拷贝" class="headerlink" title="数组的浅拷贝"></a>数组的浅拷贝</h5><p>slice()</p>
<p>concat()</p>
<h4 id="手写浅拷贝"><a href="#手写浅拷贝" class="headerlink" title="手写浅拷贝"></a>手写浅拷贝</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> shallowClone = <span class="function">(<span class="params">target</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="keyword">typeof</span> target === <span class="string">&#x27;object&#x27;</span> &amp;&amp; target !== <span class="literal">null</span>)&#123;</span><br><span class="line">        <span class="keyword">const</span> cloneTarget = <span class="built_in">Array</span>.isArray(target)? []:&#123;&#125;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">let</span> prop <span class="keyword">in</span> target)&#123;</span><br><span class="line">            <span class="keyword">if</span>(target.hasOwnProperty(prop))&#123;   <span class="comment">//判断改对象是否存在该属性</span></span><br><span class="line">                cloneTarget[prop] = target[prop];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cloneTarget</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> target</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>







<h3 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h3><p>深拷贝原理：对于复杂引用类型，其在堆内存中完全开辟了一块内存地址，并将原有的对象完全复制过来存放，且新对象的修改并不会改变原对象，二者彻底实现了真正的分离</p>
<h4 id="JSON-parse-JSON-stringify-object"><a href="#JSON-parse-JSON-stringify-object" class="headerlink" title="JSON.parse(JSON.stringify(object))"></a>JSON.parse(JSON.stringify(object))</h4><p>可以使用**JSON.parse(JSON.stringify(object))**实现深拷贝,解决深层嵌套的问题（虽存在缺点，但足够满足日常开发）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">name:&#123;</span><br><span class="line">age: <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> b = <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(a))</span><br><span class="line">b.name.age =<span class="number">2</span></span><br><span class="line"><span class="built_in">console</span>.log(a.name.age)  <span class="comment">//1</span></span><br></pre></td></tr></table></figure>

<p><strong>但这个方法存在缺点：</strong></p>
<ol>
<li><p><strong>undefined（被忽略）和function（被忽略）还有symbol类型（被忽略），JSON.Stringify序列化之后的字符串中的这个键值对会消失</strong></p>
</li>
<li><p><strong>拷贝Date引用类型会变成字符串</strong></p>
</li>
<li><p><strong>无法拷贝不可以枚举的属性，</strong></p>
</li>
<li><p><strong>无法拷贝对象的原型链，</strong></p>
</li>
<li><p><strong>拷贝RegExp引用类型会变成空对象，</strong></p>
</li>
<li><p><strong>对象中含有NaN、Infinity以及-Infinity，JSON序列化的结果会变成null；如果需要可以自己手动封装函数</strong></p>
</li>
<li><p><strong>还有循环引用的对象（报错）是无法进行深拷贝的</strong></p>
</li>
</ol>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;</span><br><span class="line">b: <span class="literal">undefined</span>,</span><br><span class="line">c:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;,</span><br><span class="line">d:<span class="built_in">Symbol</span>(<span class="number">1</span>),</span><br><span class="line">e: <span class="number">132</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> b = <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(a))</span><br><span class="line"><span class="built_in">console</span>.log(b)  <span class="comment">// &#123; e: 132 &#125;</span></span><br></pre></td></tr></table></figure>

<p><strong>使用JSON.parse(JSON.stringify(obj))深拷贝循环引用的对象会报错</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123; <span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: &#123; <span class="attr">c</span>: <span class="number">2</span> &#125; &#125;</span><br><span class="line">obj.b.d = obj.b</span><br><span class="line"><span class="keyword">var</span> b = <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(obj))</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/json.jpeg"></p>
<h4 id="MessageChannel"><a href="#MessageChannel" class="headerlink" title="MessageChannel"></a>MessageChannel</h4><p><strong>还有一种建立消息通道的方法，使用MessageChannel，实例化对象，我们可以看下这个对象的属性</strong></p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/messagechannel.jpeg"></p>
<p>这是两个回调的方法，使用MessagePort.portMessage方法发送消息的时候，就会触发另一个端口的onMessage消息通道，然后port1和port2是可以相互发送消息的</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> channel = <span class="keyword">new</span> MessageChannel();</span><br><span class="line"><span class="keyword">var</span> port1 = channel.port1;</span><br><span class="line"><span class="keyword">var</span> port2 = channel.port2;</span><br><span class="line">port1.onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;port2对port1说：&quot;</span>+event.data);</span><br><span class="line">&#125;</span><br><span class="line">port2.onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;port1对port2说：&quot;</span>+event.data);</span><br><span class="line">&#125;</span><br><span class="line">port1.postMessage(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line">port2.postMessage(<span class="string">&quot;Hi&quot;</span>);</span><br><span class="line">输出的结果：</span><br><span class="line"><span class="comment">//port1对port2说：Hello</span></span><br><span class="line"><span class="comment">//port2对port1说：Hi</span></span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<p><strong>通过MessageChannel实例的postMessage()方法传输的message参数是深拷贝的，所以可以使用MessageChannel实现深拷贝</strong></p>
<p>//深拷贝函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">deepClone</span>(<span class="params">val</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="params">resolve</span>=&gt;</span>&#123;</span><br><span class="line">        <span class="keyword">const</span> &#123;port1,port2&#125; = <span class="keyword">new</span> MessageChannel()</span><br><span class="line">        port2.onmessage = <span class="function"><span class="params">e</span>=&gt;</span> resolve(e.data)</span><br><span class="line">        port1.postMessage(val)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//定义一个包含undefined的对象</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    a: <span class="number">1</span>,</span><br><span class="line">    b:<span class="literal">undefined</span>,</span><br><span class="line">    c:&#123;</span><br><span class="line">        d:<span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//循环引用</span></span><br><span class="line">obj.c.e = obj.c</span><br><span class="line">    <span class="comment">//注意这里的方法是异步的</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">const</span> clone = <span class="keyword">await</span> deepClone(obj)</span><br><span class="line">&#125;</span><br><span class="line">test()</span><br></pre></td></tr></table></figure>



<h4 id="手写深拷贝"><a href="#手写深拷贝" class="headerlink" title="手写深拷贝"></a>手写深拷贝</h4><h5 id="基础版（递归实现）"><a href="#基础版（递归实现）" class="headerlink" title="基础版（递归实现）"></a>基础版（递归实现）</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">deepClone</span>(<span class="params">obj</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> cloneObj= &#123;&#125;</span><br><span class="line">	<span class="keyword">for</span>(<span class="keyword">let</span> key <span class="keyword">in</span> obj)&#123;</span><br><span class="line">    	<span class="keyword">if</span>(<span class="keyword">typeof</span> obj[key] === <span class="string">&#x27;object&#x27;</span>)&#123; <span class="comment">//是对象就再次调用该函数递归</span></span><br><span class="line">        	cloneObj[key] = deepClone(obj[key])</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            cloneObj[key] = obj[key] <span class="comment">//基本类型的话直接复制值</span></span><br><span class="line">        &#125;</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="keyword">return</span> cloneObj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>缺陷:</p>
<ol>
<li><p>这个基础版的深拷贝函数并不能复制不可枚举的属性以及Symbol类型</p>
</li>
<li><p>这种方法只是针对普通的引用类型的值做递归复制</p>
</li>
<li><p>对象的属性里面成环，即循环引用没有解决</p>
</li>
</ol>
<h5 id="改进："><a href="#改进：" class="headerlink" title="改进："></a>改进：</h5><p>1.针对能够遍历对象的<strong>不可枚举属性以及Symbol</strong>类型，我们可以使用<strong>Reflect.ownKeys</strong>方法</p>
<p>2.当参数为<strong>Date、RegExp</strong>类型，则直接生成有一个<strong>新的实例返回</strong></p>
<p>3.利用Object的<strong>gerOwnPropertyDescriptors</strong>方法可以<strong>获得对象的所有属性</strong>，以及对应的特性，顺便结合Object的<strong>create</strong>方法创建一个新对象，并<strong>继承传入原对象的原型链</strong></p>
<p>4.利用<strong>WeakMap</strong>类型作为Hash表，因为WeakMap是弱引用类型，可以有效防止内存泄漏，作为<strong>检测循环引用</strong>很有帮助，如果存在循环，则引用直接返回WeakMap存储的值</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> isComplexDataType = <span class="function"><span class="params">obj</span>=&gt;</span>(<span class="keyword">typeof</span> obj === <span class="string">&#x27;object&#x27;</span> || <span class="keyword">typeof</span> obj === <span class="string">&#x27;function&#x27;</span>) &amp;&amp; (obj !== <span class="literal">null</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> deepClone = <span class="function"><span class="keyword">function</span>(<span class="params">obj,hash = <span class="keyword">new</span> <span class="built_in">WeakMap</span>()</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(obj.constructor === <span class="built_in">Date</span>) <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Date</span>(obj) <span class="comment">//日期对象直接返回一个新的日期对象</span></span><br><span class="line">    <span class="keyword">if</span>(obj.constructor === <span class="built_in">RegExp</span>) <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">RegExp</span>(obj) <span class="comment">//正则对象直接返回一个新的正则对象</span></span><br><span class="line">    <span class="comment">//如果循环引用了就用WeakMap来解决</span></span><br><span class="line">    <span class="keyword">if</span>(hash.has(obj)) <span class="keyword">return</span> hash.get(obj)</span><br><span class="line">    <span class="keyword">let</span> allDesc = <span class="built_in">Object</span>.getOwnPropertyDescriptors(obj) <span class="comment">// 遍历传入参数所有键的特性</span></span><br><span class="line">    <span class="keyword">let</span> cloneObj = <span class="built_in">Object</span>.create(<span class="built_in">Object</span>.getPrototypeOf(obj),allDesc)  <span class="comment">// 继承原型链</span></span><br><span class="line">    hash.set(obj,cloneObj)</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">let</span> key <span class="keyword">of</span> <span class="built_in">Reflect</span>.ownKeys(obj))&#123; <span class="comment">//Reflect.ownKeys返回一个包含所有自身属性（不包含继承属性）的数组</span></span><br><span class="line">        cloneObj[key] = (isComplexDataType(obj[key]) &amp;&amp; <span class="keyword">typeof</span> obj[key] !== <span class="string">&#x27;function&#x27;</span>) ? deepClone(obj[key],hash) : obj[key]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> cloneObj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h6 id="强引用和弱引用"><a href="#强引用和弱引用" class="headerlink" title="强引用和弱引用:"></a><strong>强引用和弱引用:</strong></h6><p>强引用：JavaScript的对象的引用是强保留，只要持有对象的引用，它就不会被垃圾回收</p>
<p>弱引用： 若一个对象只被弱引用所引用，则被认为是不可访问或者可弱访问，在没有其他引用存在的时候垃圾回收能正常进行 （弱引用对象的key是不可枚举的）</p>
<h3 id="浏览器垃圾回收机制"><a href="#浏览器垃圾回收机制" class="headerlink" title="浏览器垃圾回收机制"></a>浏览器垃圾回收机制</h3><p>浏览器的垃圾回收机制，简称GC，会周期性的执行垃圾回收释放不需要的内存</p>
<p>垃圾回收机制的策略有两种：</p>
<h4 id="标记清除法"><a href="#标记清除法" class="headerlink" title="标记清除法"></a>标记清除法</h4><p>当变量离开环境的时候，标记为”离开环境“</p>
<h4 id="引用计数法"><a href="#引用计数法" class="headerlink" title="引用计数法"></a>引用计数法</h4><h3 id="V8引擎"><a href="#V8引擎" class="headerlink" title="V8引擎"></a>V8引擎</h3><h4 id="执行流程"><a href="#执行流程" class="headerlink" title="执行流程"></a>执行流程</h4><h4 id="v8引擎垃圾回收机制"><a href="#v8引擎垃圾回收机制" class="headerlink" title="v8引擎垃圾回收机制"></a>v8引擎垃圾回收机制</h4><p>新生代</p>
<p>老生代</p>
<h3 id="ES6"><a href="#ES6" class="headerlink" title="ES6"></a>ES6</h3><h4 id="let-const"><a href="#let-const" class="headerlink" title="let const"></a>let const</h4><p>let存在局部作用域</p>
<p>const定义的的基本类型的值是不可以第二次赋值修改的，而一般的用来定义引用类型的变量</p>
<p>var是全局作用域，var定义的变量会出现变量提升,变量声明提升到当前作用域的顶部，**(function也会出现变量提升而且优先级比var高<strong>如果两者同名优先输出function即使是function后定义，整个函数提升到作用域顶部)，</strong>var会挂载到window上，const和let不存在变量提升，不会挂载到window上**</p>
<p><strong>let、const <strong>因为</strong>暂时性死区</strong>的原因，不能在声明前使用   </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(a)</span><br><span class="line">  <span class="keyword">let</span> a</span><br><span class="line">&#125;</span><br><span class="line">test() </span><br><span class="line"><span class="comment">//报错如下截图</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/%E6%8A%A5%E9%94%99.png"></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">1</span> </span><br><span class="line"><span class="comment">//等价于 </span></span><br><span class="line"><span class="keyword">var</span> a </span><br><span class="line">a = <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//function同理</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span></span></span><br><span class="line"><span class="function"><span class="title">a</span> = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;</span></span><br></pre></td></tr></table></figure>



<p>var和function的变量提升—-例如：function的优先级高于var</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(a)  <span class="comment">// ƒ a()&#123;&#125;</span></span><br><span class="line"><span class="keyword">var</span> a = <span class="number">1</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>)</span>&#123;&#125;</span><br></pre></td></tr></table></figure>



<h4 id="Symbol"><a href="#Symbol" class="headerlink" title="Symbol"></a>Symbol</h4><h4 id="解构"><a href="#解构" class="headerlink" title="解构"></a>解构</h4><h4 id="扩展运算符-…）"><a href="#扩展运算符-…）" class="headerlink" title="扩展运算符(…）"></a>扩展运算符(…）</h4><h4 id="模板字符串"><a href="#模板字符串" class="headerlink" title="模板字符串"></a>模板字符串</h4><h4 id="Set，Map，WeakMap"><a href="#Set，Map，WeakMap" class="headerlink" title="Set，Map，WeakMap"></a>Set，Map，WeakMap</h4><h4 id="filter，reduce，includes"><a href="#filter，reduce，includes" class="headerlink" title="filter，reduce，includes"></a>filter，reduce，includes</h4><h4 id="class"><a href="#class" class="headerlink" title="class"></a>class</h4><h4 id="异步"><a href="#异步" class="headerlink" title="异步"></a>异步</h4><h4 id="ES-Module"><a href="#ES-Module" class="headerlink" title="ES Module"></a>ES Module</h4><h3 id="异步-1"><a href="#异步-1" class="headerlink" title="异步"></a>异步</h3><h4 id="generator："><a href="#generator：" class="headerlink" title="generator："></a>generator：</h4><p>并发和并行</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ajax</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">yield</span> ajax(url,<span class="function">()=&gt;</span>&#123;&#125;)</span><br><span class="line">    <span class="keyword">yield</span> ajax(url,<span class="function">()=&gt;</span>&#123;&#125;)</span><br><span class="line">    <span class="keyword">yield</span> ajax(url,<span class="function">()=&gt;</span>&#123;&#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> a = ajax()</span><br><span class="line"><span class="keyword">let</span> result1 = ajax.next()</span><br><span class="line"><span class="keyword">let</span> result2 = ajax.next()</span><br><span class="line"><span class="keyword">let</span> result3 = ajax.next()</span><br></pre></td></tr></table></figure>

<p><strong>Generator</strong>会返回一个迭代器</p>
<p>当第一次执行next的时候，便会停留在第一个yield处，在第二次执行next的时候，传入的参数等于上一个yield的返回值，如果不传参，yield返回undefined</p>
<p><strong>所以这个迭代器可以解决回调地狱的问题</strong></p>
<h4 id="promise："><a href="#promise：" class="headerlink" title="promise："></a>promise：</h4><p>有三个状态，pending(等待) ,fulfilled(完成),rejected(拒绝)</p>
<h5 id="手写promise的实现"><a href="#手写promise的实现" class="headerlink" title="手写promise的实现"></a>手写promise的实现</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> PENDING = <span class="string">&#x27;pending&#x27;</span></span><br><span class="line"><span class="keyword">const</span> FULFILLED = <span class="string">&#x27;fulfilled&#x27;</span></span><br><span class="line"><span class="keyword">const</span> REJECTED = <span class="string">&#x27;rejected&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Promise</span>(<span class="params">fn</span>)</span>&#123;</span><br><span class="line">	<span class="keyword">let</span> that = <span class="built_in">this</span></span><br><span class="line">	that.status = PENDING</span><br><span class="line">	that.value = <span class="string">&#x27;&#x27;</span></span><br><span class="line">	that.resolveCallback = []</span><br><span class="line">	that.rejectCallback = []</span><br><span class="line">	</span><br><span class="line">	<span class="keyword">var</span> resolve = <span class="function"><span class="keyword">function</span>(<span class="params">value</span>)</span>&#123;</span><br><span class="line">        queueMicrotask(<span class="function">()=&gt;</span>&#123; </span><br><span class="line">			<span class="keyword">if</span>(that.value = PENDING)&#123;</span><br><span class="line">				that.value = value</span><br><span class="line">				that.status = FULFILLED</span><br><span class="line">           	 	that.resolveCallback.map(<span class="function"><span class="params">cb</span>=&gt;</span>cb(that.value))</span><br><span class="line">			&#125;</span><br><span class="line">        &#125;)</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">var</span> reject = <span class="function"><span class="keyword">function</span>(<span class="params">value</span>)</span>&#123;</span><br><span class="line">        queueMicrotask(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">			<span class="keyword">if</span>(that.status = PENDING)&#123;</span><br><span class="line">				that.value = value</span><br><span class="line">				that.status = REJECTED</span><br><span class="line">            	that.rejectCallback.map(<span class="function"><span class="params">cb</span>=&gt;</span>cb(that.value))</span><br><span class="line">			&#125;</span><br><span class="line">       	&#125;)</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">try</span>&#123;</span><br><span class="line">		fn(resolve,reject)</span><br><span class="line">	&#125;<span class="keyword">catch</span>(err)&#123;</span><br><span class="line">		reject(err)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Promise</span>.prototype.then = <span class="function"><span class="keyword">function</span>(<span class="params">onFulfilled,onRejected</span>)</span>&#123;</span><br><span class="line">    onFulfilled = <span class="keyword">typeof</span> onFulfilled === <span class="string">&#x27;function&#x27;</span> ? onFulfilled : <span class="function"><span class="params">v</span>=&gt;</span>v</span><br><span class="line">	onRejected = <span class="keyword">typeof</span> onRejected === <span class="string">&#x27;function&#x27;</span> ? onRejected : <span class="function"><span class="params">r</span>=&gt;</span>&#123;<span class="keyword">throw</span> r&#125;</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">this</span>.status === PENDING)&#123;</span><br><span class="line">       <span class="built_in">this</span>.resolveCallback.push(onFulfilled)</span><br><span class="line">       <span class="built_in">this</span>.rejectCallback.push(onRejected)</span><br><span class="line">     &#125;</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">this</span>.status === FULFILLED)&#123;</span><br><span class="line">       onFulfilled(<span class="built_in">this</span>.value)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">this</span>.status === REJECTED)&#123;</span><br><span class="line">       onRejected(<span class="built_in">this</span>.value)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve,rejected</span>)=&gt;</span>&#123;</span><br><span class="line">    resolve(<span class="string">&#x27;res&#x27;</span>)</span><br><span class="line">&#125;).then(<span class="function"><span class="params">res</span>=&gt;</span>&#123;&#125;)</span><br></pre></td></tr></table></figure>

<p>Promise不能通过return中断，在then中使用return会成为下一then的参数返回(return的值被Promise.resolve()包装)，then返回的是一个新的Promise</p>
<p><strong>通过try catch 在then里面抛出异常错误中断then</strong></p>
<p>通过Promise也可以解决回调地狱，但如果回调太多，后面也会需要写多个then，如果太多的回调then看着好像也不是太优雅</p>
<h4 id="async-和-await"><a href="#async-和-await" class="headerlink" title="async 和 await:"></a>async 和 await:</h4><p><strong>一个普通函数前面加修饰符 async 该函数会返回一个Promise</strong></p>
<p>如果异步方法是后一个与前一个是由依赖关系的，使用async ，await是比较好的解决方案，await可以将异步变成同步，当上一个await执行完毕后才执行下一个await，当然await是需要配合async使用的，</p>
<p>但是如果多个异步方法直接没有相互依赖的关系，那么还是少用吧，毕竟await会导致性能降低，执行需要等待上一个await执行完毕才执行下一个</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 以下代码没有依赖性的话，完全可以使用 Promise.all 的方式</span></span><br><span class="line">  <span class="comment">// 如果有依赖性的话，其实就是解决回调地狱的例子了</span></span><br><span class="line">  <span class="keyword">await</span> fetch(url)</span><br><span class="line">  <span class="keyword">await</span> fetch(url1)</span><br><span class="line">  <span class="keyword">await</span> fetch(url2)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>await内部使用的迭代器Generator实现的，所以await是generator和Promise的语法糖</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">await</span> async2()</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async2 end&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//相当于下面</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve,reject</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>)</span><br><span class="line">	resolve(<span class="built_in">Promise</span>.resolve())</span><br><span class="line">	<span class="built_in">console</span>.log(<span class="string">&#x27;async2 end&#x27;</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>





<h3 id="定时函数"><a href="#定时函数" class="headerlink" title="定时函数"></a>定时函数</h3><p>setTimeout、setInterval、requestAnimationFrame</p>
<p>setTimeout，setInterval不是设定延时多久，多久后才执行，因为<strong>js是单线程执行的</strong>，如果<strong>前面的代码影响性能</strong>了，也会<strong>导致setTimeout，setInterval不会按期执行</strong></p>
<p><strong>如果你有循环定时器的需求，可以通过requestAnimationFrame来实现</strong></p>
<p>requestAnimationFrame自带函数节流功能，在不掉帧的情况下，可以保证在16.6毫秒只执行一次，并且该函数的延时效果是精准的，没有其他定时器时间不准的问题（可以通过该函数实现setTimeout）</p>
<h3 id="Event-loop"><a href="#Event-loop" class="headerlink" title="Event loop"></a>Event loop</h3><p>js代码是放在执行栈里面的，代码的执行是先执行<code>&lt;script&gt;</code>第一个宏任务，将所有的function函数放在执行栈里面，当遇到异步的方法的时候，会将这个异步的方法放Task队列中（Task队列分为宏任务队列macrotask，微任务队microtask），es6中microtask称为jobs，macrotask称为task，当执行栈的function都出栈执行完毕后，就会将微任务microtask加入执行栈执行，当执行栈的所有的微任务执行完毕后，就会执行下一个宏任务macrotask(进行下一轮的event loop)，按着这样一直循环</p>
<p><code>async 中的await是执行后会返回一个promise，在将这个promise加入microtask任务队列</code></p>
<p><code>常见的微任务</code>：process.nextTick ，promise ，MutationObserver，queueMircotask</p>
<p><code>常见的宏任务</code>： script ， setTimeout ，setInterval ，setImmediate ，I/O ，UI rendering</p>
<h5 id="node中的event-loop"><a href="#node中的event-loop" class="headerlink" title="node中的event loop"></a>node中的event loop</h5><p>（node中的event loop在10版本之前和浏览器中的是不相同的东西，10之后都几乎是一样了）</p>
<p><code>那下面我们主要讲node10版本之前的</code>：</p>
<p>node中event loop 中是六个阶段，每当进入某一个阶段的时候，都会对应的在回调队列中取函数取执行</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/image-20210415090212797.png" alt="image-20210415090212797"></p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/image-20210416090349533.png" alt="image-20210416090349533"></p>
<p><strong>timer</strong> 阶段会执行<strong>setTimeout</strong> 和 <strong>setInterval</strong> 回调，并且由 <strong>poll</strong> 阶段控制的，定时器在node中的也不是准时执行的</p>
<p><strong>I/O</strong> <strong>callbacks</strong>阶段会处理一些上一轮循环中的少数未执行的I/O回调</p>
<p>除了以下操作的回调函数，其他的回调函数都在这个阶段执行。</p>
<blockquote>
<ul>
<li><code>setTimeout()</code>和<code>setInterval()</code>的回调函数</li>
<li><code>setImmediate()</code>的回调函数</li>
<li>用于关闭请求的回调函数，比如<code>socket.on(&#39;close&#39;, ...)</code></li>
</ul>
</blockquote>
<p><strong>idle，prepare</strong>  阶段libuv内部实现</p>
<p><strong>poll 阶段</strong>： </p>
<p>1.回到timer阶段执行回调</p>
<p>2.执行I/O回调</p>
<ul>
<li><p>如果poll队列不为空，会遍历回调队列并同步执行，直到队列为空或者达到系统限制</p>
</li>
<li><p>如果poll队列为空时，会发生两件事发生：</p>
<p>1.如果有setImmediate回调需要执行，poll阶段会停止并且进入到check阶段执行回调</p>
<p>2.如果没有setImmediate回调需要执行，会等待回调被加入到队列中并立即执行回调，这里同样会有个超时时间设置防止一直等待下去</p>
</li>
</ul>
<p>设定了timer的话poll队列为空，则会判断是否有timer超时，如果有的话会回到timer阶段执行回调</p>
<p><strong>check 阶段</strong>：</p>
<p>check阶段执行setImmediate    setImmediate(callback[, …args])接受callback并将其添加到事件队列(特别是立即执行队列)中，setImmediate()和process.nextTick()这两个函数是使我们能够控制事件循环中代码的执行顺序，这两个函数在事件队列中调度我们的回调处理程序，但是他们在事件循环的不同阶段执行</p>
<p><strong>close callbacks 阶段</strong></p>
<p>该阶段执行关闭请求的回调函数，比如close事件<code>socket.on(&#39;close&#39;, ...)</code>。</p>
<p><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/image-20210415085609715.png" alt="image-20210415085609715"></p>
<h3 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h3><h4 id="立即执行函数"><a href="#立即执行函数" class="headerlink" title="立即执行函数:"></a>立即执行函数:</h4><p>早期在立即执行函数里面（沙箱–小环境），通过函数作用域解决命名冲突的问题，污染全局作用域的问题，实现模块化</p>
<h4 id="AMD和CMD实现模块化："><a href="#AMD和CMD实现模块化：" class="headerlink" title="AMD和CMD实现模块化："></a>AMD和CMD实现模块化：</h4><h5 id="AMD"><a href="#AMD" class="headerlink" title="AMD:"></a>AMD:</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">define([<span class="string">&#x27;./a&#x27;</span>,<span class="string">&#x27;./b&#x27;</span>],<span class="function"><span class="keyword">function</span>(<span class="params">a,b</span>)</span>&#123;</span><br><span class="line">    <span class="comment">//加载模块完毕可以使用</span></span><br><span class="line">    a.do()</span><br><span class="line">    b.do() </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h5 id="CMD"><a href="#CMD" class="headerlink" title="CMD:"></a>CMD:</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">define(<span class="function"><span class="keyword">function</span>(<span class="params"><span class="built_in">require</span>,<span class="built_in">exports</span>,<span class="built_in">module</span></span>)</span>&#123;</span><br><span class="line">    <span class="comment">//加载模块</span></span><br><span class="line">    <span class="comment">//可以把require写在函数体的任意地方实现延迟加载</span></span><br><span class="line">    <span class="keyword">var</span> <span class="built_in">require</span>(<span class="string">&#x27;./a&#x27;</span>)</span><br><span class="line">    a.doSomething()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h4 id="CommonJS（动态导入）"><a href="#CommonJS（动态导入）" class="headerlink" title="CommonJS（动态导入）"></a>CommonJS（动态导入）</h4><p>（加载模块是同步的，即只有加载完成，才能执行后面的操作）</p>
<p>CommonJS在Node、webpack等也常见到</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//a.js</span></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    a:<span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line">或者</span><br><span class="line"><span class="keyword">export</span>.a = <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//b.js</span></span><br><span class="line"><span class="keyword">var</span> <span class="built_in">module</span> = <span class="built_in">require</span>(<span class="string">&#x27;./a.js&#x27;</span>)</span><br><span class="line"><span class="built_in">module</span>.a  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="built_in">module</span> = <span class="built_in">require</span>(<span class="string">&#x27;./a.js&#x27;</span>)</span><br><span class="line"><span class="built_in">module</span>.a</span><br><span class="line"><span class="comment">//这里包装了一层立即执行函数，这样就不会污染全局变量了</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    a:<span class="number">1</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//module的实现原理</span></span><br><span class="line"><span class="keyword">var</span> <span class="built_in">module</span> = &#123;</span><br><span class="line">    id: <span class="string">&#x27;xxx&#x27;</span>,   <span class="comment">//对应的id</span></span><br><span class="line">    <span class="built_in">exports</span>:&#123;&#125;    <span class="comment">//空对象用于存储导出去的内容</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> <span class="built_in">exports</span> = modele.exports  <span class="comment">//这个为什么exports和module.exports用法相似的原因，另外这里exports和module.exports共享了相同的地址，所以通过改变对象的属性的值exports和module.exports都会被修改了，所以不能对exports进行直接赋值否则两者指向的内存不再是同一个</span></span><br><span class="line"><span class="keyword">var</span> load = <span class="function"><span class="keyword">function</span>(<span class="params"><span class="built_in">module</span></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> a = <span class="number">1</span></span><br><span class="line">    <span class="built_in">module</span>.exports = a</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">module</span>.exports</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//当require 的时候去找到独特的id，然后将要使用的东西用立即执行函数包装下</span></span><br></pre></td></tr></table></figure>

<p>CommonJS的所有代码在模块的作用域，不会污染全局作用域，<strong>导出时都是值拷贝，就算导出的值变了，导入的值也不会发生改变</strong></p>
<p>口说无凭，看下面例子</p>
<p>//a.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> num = <span class="number">1</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    num++</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    num: num,</span><br><span class="line">    add: add</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>//main.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span>  a = <span class="built_in">require</span>(<span class="string">&#x27;./a.js&#x27;</span>)</span><br><span class="line"><span class="built_in">console</span>.log(a.num) <span class="comment">//1</span></span><br><span class="line">a.add()</span><br><span class="line"><span class="built_in">console</span>.log(a.num) <span class="comment">//1</span></span><br></pre></td></tr></table></figure>

<h5 id="exports"><a href="#exports" class="headerlink" title="exports:"></a>exports:</h5><p>//dome.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;dome&quot;</span>);</span><br><span class="line"><span class="built_in">exports</span>.hello = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line"><span class="built_in">exports</span>.add = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">exports</span>.person = &#123;</span><br><span class="line">    name: <span class="string">&quot;小明&quot;</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 这里能打印出外部引用添加的exports的变量</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">exports</span>);</span><br><span class="line">&#125;, <span class="number">2000</span>);</span><br></pre></td></tr></table></figure>

<p>//index.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;start&quot;</span>);</span><br><span class="line"><span class="keyword">var</span> dome = <span class="built_in">require</span>(<span class="string">&#x27;./dome.js&#x27;</span>)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;end&quot;</span>,dome);</span><br><span class="line"><span class="comment">// 同一个引用外部可以改变exports导出的内容</span></span><br><span class="line">dome.additional = <span class="string">&quot;test&quot;</span></span><br></pre></td></tr></table></figure>

<p>终端执行 node index.js 打印结果为</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">start</span><br><span class="line">dome</span><br><span class="line">end &#123; <span class="attr">hello</span>: <span class="string">&#x27;hello&#x27;</span>, <span class="attr">add</span>: [<span class="built_in">Function</span>], <span class="attr">person</span>: &#123; <span class="attr">name</span>: <span class="string">&#x27;小明&#x27;</span> &#125; &#125;</span><br><span class="line"><span class="comment">//两秒后打印所有的exports的变量</span></span><br><span class="line">&#123;</span><br><span class="line">hello: <span class="string">&#x27;hello&#x27;</span>,</span><br><span class="line">add: [<span class="built_in">Function</span>],</span><br><span class="line">person: &#123; <span class="attr">name</span>: <span class="string">&#x27;小明&#x27;</span> &#125;,</span><br><span class="line">additional: <span class="string">&#x27;test&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="module-exports"><a href="#module-exports" class="headerlink" title="module.exports:"></a>module.exports:</h5><p>//index.js</p>
<p>代码不变</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;start&quot;</span>);</span><br><span class="line"><span class="keyword">var</span> dome = <span class="built_in">require</span>(<span class="string">&#x27;./dome.js&#x27;</span>)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;end&quot;</span>,dome);</span><br><span class="line"><span class="comment">// 同一个引用外部可以改变exports导出的内容</span></span><br><span class="line">dome.additional = <span class="string">&quot;test&quot;</span></span><br></pre></td></tr></table></figure>

<p>//dome.js 加入module.exports的应用</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;dome&quot;</span>);</span><br><span class="line"><span class="built_in">exports</span>.hello = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line"><span class="built_in">exports</span>.add = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">exports</span>.person = &#123;</span><br><span class="line">    name: <span class="string">&quot;小明&quot;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 外部的引用会被这个module.exports取代 会覆盖所有的exports</span></span><br><span class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">minus</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a - b;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 这里能打印出外部引用添加的exports的变量</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">exports</span>);</span><br><span class="line">&#125;, <span class="number">2000</span>);</span><br></pre></td></tr></table></figure>

<p>终端执行 node index.js 打印结果为</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">start</span><br><span class="line">dome</span><br><span class="line">end <span class="function"><span class="keyword">function</span> <span class="title">minus</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line"><span class="keyword">return</span> a - b;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//两秒后打印所有的exports的变量</span></span><br><span class="line">&#123; <span class="attr">hello</span>: <span class="string">&#x27;hello&#x27;</span>, <span class="attr">add</span>: [<span class="built_in">Function</span>], <span class="attr">person</span>: &#123; <span class="attr">name</span>: <span class="string">&#x27;小明&#x27;</span> &#125; &#125;</span><br></pre></td></tr></table></figure>

<p><strong>显然外部的引用会被这个module.exports取代,会覆盖所有的exports（</strong>这里exports和module.exports共享了相同的地址<strong>）</strong></p>
<h4 id="ES-Module-静态导入"><a href="#ES-Module-静态导入" class="headerlink" title="ES Module(静态导入)"></a>ES Module(静态导入)</h4><p>使用ES Module实现模块化（原生方法）</p>
<p>ES Module最终会编译成 require / exports 执行</p>
<p>//引入模块的方式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> xxx <span class="keyword">from</span> <span class="string">&#x27;./a.js&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; xxx &#125; <span class="keyword">from</span> <span class="string">&#x27;./a.js&#x27;</span></span><br></pre></td></tr></table></figure>

<p>//导出模块的方式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>ES Module采用实时绑定的方式，<strong>导入导出的值都是指向同一个内存地址，导入值会随着导出值变化</strong></p>
<p>//a.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line"><span class="keyword">var</span> num = <span class="number">1</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    num++</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>//main.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> a <span class="keyword">from</span> <span class="string">&#x27;./a.js&#x27;</span></span><br><span class="line"><span class="built_in">console</span>.log(a.num) <span class="comment">//1</span></span><br><span class="line">a.add()</span><br><span class="line"><span class="built_in">console</span>.log(a.num) <span class="comment">//2</span></span><br></pre></td></tr></table></figure>

</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">mozihao</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://mo_zi_hao.gitee.io/blog/posts/449/">https://mo_zi_hao.gitee.io/blog/posts/449/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://mo_zi_hao.gitee.io/blog" target="_blank">mozihao</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/JavaScript%E5%9F%BA%E7%A1%80/">JavaScript基础</a></div><div class="post_share"><div class="social-share" data-image="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/26&amp;gp=0.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/blog/posts/23125/"><img class="prev-cover" src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/745.jpg" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">gitlab-cicd</div></div></a></div><div class="next-post pull-right"><a href="/blog/posts/35506/"><img class="next-cover" src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/1234.jpg" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">微信小程序</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-avatar is-center"><img class="avatar-img" src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/%E6%B5%B7%E8%B4%BC008.jpg" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">mozihao</div><div class="author-info__description">if you risk nothing,then you risk anthing</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">24</div></a></div><div class="card-info-data-item is-center"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">16</div></a></div><div class="card-info-data-item is-center"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">11</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://gitee.com/mo_zi_hao"><i class="iconfont icon-gitee-fill-round"></i><span>我的Gitee</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://gitee.com/mo_zi_hao" target="_blank" title="Gitee"><i class="fab iconfont icon-gitee-fill-round"></i></a><a class="social-icon" href="https://github.com/mmCrazy" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="https://blog.csdn.net/xiaomohhh?spm=1001.2101.3001.5343" target="_blank" title="CSDN"><i class="fab iconfont icon-csdn"></i></a><a class="social-icon" href="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/qrcode_for_gh_d35478eda980_430.jpg" target="_blank" title="公众号"><i class="fab iconfont icon-weixingongzhonghao"></i></a><a class="social-icon" href="mailto:747304031@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">如文章中有哪些错漏，欢迎各位前端的大佬与我交流并指正，谢谢!!</br>邮箱：747304031@qq.com</br>公众号：一起写前端bug</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B"><span class="toc-number">1.</span> <span class="toc-text">基本类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD%E2%80%93typeof"><span class="toc-number">2.</span> <span class="toc-text">类型判断–typeof</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E5%88%A4%E6%96%AD%E2%80%94instanceof"><span class="toc-number">3.</span> <span class="toc-text">对象判断—instanceof</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#instanceof%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="toc-number">3.1.</span> <span class="toc-text">instanceof实现原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2"><span class="toc-number">4.</span> <span class="toc-text">类型转换</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BD%ACBoolean"><span class="toc-number">5.</span> <span class="toc-text">转Boolean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E8%BD%AC%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B"><span class="toc-number">6.</span> <span class="toc-text">对象转基本类型</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9D%A2%E8%AF%95%E9%A2%98%EF%BC%9A"><span class="toc-number">6.1.</span> <span class="toc-text">面试题：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9B%9B%E5%88%99%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">7.</span> <span class="toc-text">四则运算符</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8A%A0%E6%B3%95%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">7.1.</span> <span class="toc-text">加法运算符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%AF%94%E8%BE%83%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">7.2.</span> <span class="toc-text">比较运算符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9D%A2%E8%AF%95%E9%A2%98"><span class="toc-number">7.3.</span> <span class="toc-text">面试题</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AD%89%E5%8F%B7"><span class="toc-number">8.</span> <span class="toc-text">等号 &#x3D;&#x3D;</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B3%A8%E6%84%8F%EF%BC%9A"><span class="toc-number">8.1.</span> <span class="toc-text">注意：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%A7%A3%EF%BC%9A-true"><span class="toc-number">8.2.</span> <span class="toc-text">解：[] &#x3D;&#x3D; ![]     &#x2F;&#x2F;true</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%A7%A3%EF%BC%9A-false"><span class="toc-number">8.3.</span> <span class="toc-text">解：{} &#x3D;&#x3D; !{}    &#x2F;&#x2F;false</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%A8%E7%AD%89"><span class="toc-number">9.</span> <span class="toc-text">全等 &#x3D;&#x3D;&#x3D;</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%A8%E7%AD%89%EF%BC%9A%E4%B8%8D%E5%AD%98%E5%9C%A8%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2"><span class="toc-number">9.1.</span> <span class="toc-text">全等：不存在隐式转换</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Object-is"><span class="toc-number">9.2.</span> <span class="toc-text">Object.is()</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B"><span class="toc-number">10.</span> <span class="toc-text">原型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E9%93%BE"><span class="toc-number">11.</span> <span class="toc-text">原型链</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%E5%92%8Cclass%E7%BB%A7%E6%89%BF"><span class="toc-number">12.</span> <span class="toc-text">原型继承和class继承</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%EF%BC%9A"><span class="toc-number">12.1.</span> <span class="toc-text">原型继承：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%80%9F%E7%94%A8%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E7%BB%A7%E6%89%BF%EF%BC%9A"><span class="toc-number">12.2.</span> <span class="toc-text">借用构造函数实现继承：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF%EF%BC%9A"><span class="toc-number">12.3.</span> <span class="toc-text">组合继承：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%84%E7%94%9F%E7%BB%84%E5%90%88%E7%BB%A7%E6%89%BF%EF%BC%9A"><span class="toc-number">12.4.</span> <span class="toc-text">寄生组合继承：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#class%E7%BB%A7%E6%89%BF"><span class="toc-number">12.5.</span> <span class="toc-text">class继承</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#this"><span class="toc-number">13.</span> <span class="toc-text">this</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B3%A8%E6%84%8F%EF%BC%9A-1"><span class="toc-number">13.1.</span> <span class="toc-text">注意：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99call"><span class="toc-number">13.2.</span> <span class="toc-text">手写call</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99apply"><span class="toc-number">13.3.</span> <span class="toc-text">手写apply</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99bind"><span class="toc-number">13.4.</span> <span class="toc-text">手写bind</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99call-apply-bind%E6%80%BB%E7%BB%93%EF%BC%9A"><span class="toc-number">13.5.</span> <span class="toc-text">手写call,apply,bind总结：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#new%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="toc-number">14.</span> <span class="toc-text">new的实现</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%97%AD%E5%8C%85"><span class="toc-number">15.</span> <span class="toc-text">闭包</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%97%AD%E5%8C%85%E7%9A%84%E8%BF%90%E7%94%A8%E5%9C%BA%E6%99%AF%EF%BC%9A"><span class="toc-number">15.1.</span> <span class="toc-text">闭包的运用场景：</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%98%B2%E6%8A%96%EF%BC%9A"><span class="toc-number">15.1.1.</span> <span class="toc-text">防抖：</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%8A%82%E6%B5%81%EF%BC%9A"><span class="toc-number">15.1.2.</span> <span class="toc-text">节流：</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F"><span class="toc-number">15.1.3.</span> <span class="toc-text">单例模式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">16.</span> <span class="toc-text">浅拷贝</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%9E%E7%8E%B0%E6%B5%85%E6%8B%B7%E8%B4%9D%EF%BC%9A"><span class="toc-number">16.1.</span> <span class="toc-text">实现浅拷贝：</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#ES6%E7%9A%84assign"><span class="toc-number">16.1.1.</span> <span class="toc-text">ES6的assign</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%BF%98%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E2%80%A6%E8%BF%90%E7%AE%97%E7%AC%A6%E5%AE%9E%E7%8E%B0%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">16.1.2.</span> <span class="toc-text">还可以使用…运算符实现浅拷贝</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E7%9A%84%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">16.1.3.</span> <span class="toc-text">数组的浅拷贝</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">16.2.</span> <span class="toc-text">手写浅拷贝</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B7%B1%E6%8B%B7%E8%B4%9D"><span class="toc-number">17.</span> <span class="toc-text">深拷贝</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#JSON-parse-JSON-stringify-object"><span class="toc-number">17.1.</span> <span class="toc-text">JSON.parse(JSON.stringify(object))</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#MessageChannel"><span class="toc-number">17.2.</span> <span class="toc-text">MessageChannel</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%8B%E5%86%99%E6%B7%B1%E6%8B%B7%E8%B4%9D"><span class="toc-number">17.3.</span> <span class="toc-text">手写深拷贝</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%9F%BA%E7%A1%80%E7%89%88%EF%BC%88%E9%80%92%E5%BD%92%E5%AE%9E%E7%8E%B0%EF%BC%89"><span class="toc-number">17.3.1.</span> <span class="toc-text">基础版（递归实现）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%94%B9%E8%BF%9B%EF%BC%9A"><span class="toc-number">17.3.2.</span> <span class="toc-text">改进：</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%BC%BA%E5%BC%95%E7%94%A8%E5%92%8C%E5%BC%B1%E5%BC%95%E7%94%A8"><span class="toc-number">17.3.2.1.</span> <span class="toc-text">强引用和弱引用:</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6"><span class="toc-number">18.</span> <span class="toc-text">浏览器垃圾回收机制</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4%E6%B3%95"><span class="toc-number">18.1.</span> <span class="toc-text">标记清除法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E6%B3%95"><span class="toc-number">18.2.</span> <span class="toc-text">引用计数法</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#V8%E5%BC%95%E6%93%8E"><span class="toc-number">19.</span> <span class="toc-text">V8引擎</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B"><span class="toc-number">19.1.</span> <span class="toc-text">执行流程</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#v8%E5%BC%95%E6%93%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6"><span class="toc-number">19.2.</span> <span class="toc-text">v8引擎垃圾回收机制</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES6"><span class="toc-number">20.</span> <span class="toc-text">ES6</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#let-const"><span class="toc-number">20.1.</span> <span class="toc-text">let const</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Symbol"><span class="toc-number">20.2.</span> <span class="toc-text">Symbol</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%A7%A3%E6%9E%84"><span class="toc-number">20.3.</span> <span class="toc-text">解构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6-%E2%80%A6%EF%BC%89"><span class="toc-number">20.4.</span> <span class="toc-text">扩展运算符(…）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%A8%A1%E6%9D%BF%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-number">20.5.</span> <span class="toc-text">模板字符串</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Set%EF%BC%8CMap%EF%BC%8CWeakMap"><span class="toc-number">20.6.</span> <span class="toc-text">Set，Map，WeakMap</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#filter%EF%BC%8Creduce%EF%BC%8Cincludes"><span class="toc-number">20.7.</span> <span class="toc-text">filter，reduce，includes</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#class"><span class="toc-number">20.8.</span> <span class="toc-text">class</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5"><span class="toc-number">20.9.</span> <span class="toc-text">异步</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES-Module"><span class="toc-number">20.10.</span> <span class="toc-text">ES Module</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5-1"><span class="toc-number">21.</span> <span class="toc-text">异步</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#generator%EF%BC%9A"><span class="toc-number">21.1.</span> <span class="toc-text">generator：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#promise%EF%BC%9A"><span class="toc-number">21.2.</span> <span class="toc-text">promise：</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%8B%E5%86%99promise%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="toc-number">21.2.1.</span> <span class="toc-text">手写promise的实现</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#async-%E5%92%8C-await"><span class="toc-number">21.3.</span> <span class="toc-text">async 和 await:</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0"><span class="toc-number">22.</span> <span class="toc-text">定时函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Event-loop"><span class="toc-number">23.</span> <span class="toc-text">Event loop</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#node%E4%B8%AD%E7%9A%84event-loop"><span class="toc-number">23.0.1.</span> <span class="toc-text">node中的event loop</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A8%A1%E5%9D%97%E5%8C%96"><span class="toc-number">24.</span> <span class="toc-text">模块化</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E5%87%BD%E6%95%B0"><span class="toc-number">24.1.</span> <span class="toc-text">立即执行函数:</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#AMD%E5%92%8CCMD%E5%AE%9E%E7%8E%B0%E6%A8%A1%E5%9D%97%E5%8C%96%EF%BC%9A"><span class="toc-number">24.2.</span> <span class="toc-text">AMD和CMD实现模块化：</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#AMD"><span class="toc-number">24.2.1.</span> <span class="toc-text">AMD:</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#CMD"><span class="toc-number">24.2.2.</span> <span class="toc-text">CMD:</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#CommonJS%EF%BC%88%E5%8A%A8%E6%80%81%E5%AF%BC%E5%85%A5%EF%BC%89"><span class="toc-number">24.3.</span> <span class="toc-text">CommonJS（动态导入）</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#exports"><span class="toc-number">24.3.1.</span> <span class="toc-text">exports:</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#module-exports"><span class="toc-number">24.3.2.</span> <span class="toc-text">module.exports:</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES-Module-%E9%9D%99%E6%80%81%E5%AF%BC%E5%85%A5"><span class="toc-number">24.4.</span> <span class="toc-text">ES Module(静态导入)</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/posts/1/" title="无题"><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/%E6%B5%B7%E8%B4%BC4.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="无题"/></a><div class="content"><a class="title" href="/blog/posts/1/" title="无题">无题</a><time datetime="2022-06-05T05:20:17.974Z" title="发表于 2022-06-05 13:20:17">2022-06-05</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/posts/36549/" title="编写可维护的JavaScript (代码习惯)"><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/%E6%B5%B7%E8%B4%BC4.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="编写可维护的JavaScript (代码习惯)"/></a><div class="content"><a class="title" href="/blog/posts/36549/" title="编写可维护的JavaScript (代码习惯)">编写可维护的JavaScript (代码习惯)</a><time datetime="2022-03-19T03:12:42.624Z" title="发表于 2022-03-19 11:12:42">2022-03-19</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/posts/23125/" title="gitlab-cicd"><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/745.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="gitlab-cicd"/></a><div class="content"><a class="title" href="/blog/posts/23125/" title="gitlab-cicd">gitlab-cicd</a><time datetime="2021-12-20T14:00:59.661Z" title="发表于 2021-12-20 22:00:59">2021-12-20</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/posts/449/" title="前端js基础"><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/26&amp;gp=0.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="前端js基础"/></a><div class="content"><a class="title" href="/blog/posts/449/" title="前端js基础">前端js基础</a><time datetime="2021-08-29T15:22:14.600Z" title="发表于 2021-08-29 23:22:14">2021-08-29</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/posts/35506/" title="微信小程序"><img src="https://gitee.com/mo_zi_hao/picsBed/raw/master/image/1234.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="微信小程序"/></a><div class="content"><a class="title" href="/blog/posts/35506/" title="微信小程序">微信小程序</a><time datetime="2021-08-29T15:22:14.600Z" title="发表于 2021-08-29 23:22:14">2021-08-29</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By mozihao</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div></div><hr/><div id="local-search-results"></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/blog/js/utils.js"></script><script src="/blog/js/main.js"></script><script src="/blog/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="/blog/js/search/local-search.js"></script><div class="js-pjax"></div><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="false"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>